<?php

declare(ENCODING = 'UTF-8');

/*                                                                        *
 * This script is part of the TYPO3 project - inspiring people to share!  *
 *                                                                        *
 * TYPO3 is free software; you can redistribute it and/or modify it under *
 * the terms of the GNU General Public License version 2 as published by  *
 * the Free Software Foundation.                                          *
 *                                                                        *
 * This script is distributed in the hope that it will be useful, but     *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *	
 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
 * Public License for more details.                                       *
 *                                                                        */	

/**
 * @package auxo
 * @subpackage Web
 * @version $Id$
 */

/**	
 * The Web Request Handler
 *
 * This class handles any kind of web requests. It uses  controller resolvers to determine a 
 * controller. If a controller is found it handles the request finally. Resolvers are processed as 
 * long as no controller has been determined. If no controller has been found by any resolver and 
 * "NoControllerFound" exception is thrown. Exceptions might be consumed using request exception 
 * handlers in order to e.g. to forward to an error or default controller. Requests might be filtered 
 * using a chain of filter instances. A Filter chain has to injected in this request handler in order 
 * to use this feature.
 * 
 * @package auxo
 * @subpackage Web
 * @version $Id$	
 * @copyright Copyright belongs to the respective authors
 * @author AHN
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
 */
class  tx_auxo_RequestWebHandler implements tx_auxo_RequestHandlerInterface, tx_auxo_PriorityInterface  {

	/**
	 * Priority of this Request Handler
	 *
	 */
	const HANDLER_PRIORITY = 50;
	
	/**
	 * A list of Controller Resolver 
	 *
	 * @var tx_auxo_HashArray
	 */
	protected $resolvers = NULL;
	
	/**
	 * The Component Factory
	 *
	 * @var tx_auxo_ComponentFactory
	 */
	protected $factory = NULL;

	/**
	 * A Filter Chain
	 *
	 * @var tx_auxo_FilterChain
	 */
	protected $filterChain = NULL;
		
	/**
	 * Returns true for all web requests
	 *
	 * @param tx_auxo_Request $request a request
	 * @return boolean $canHandle true if this request can be handled
	 */
	public function canHandle(tx_auxo_Request $request) {
		return strcmp(sapiname(), 'CLI') != 0 ? true : false;
	}

	/**
	 * Setter for the Controller Resolver
	 *
	 * @param tx_auxo_ControllerResolverInterface $controllerResolver
	 */
	public function setControllerResolvers(tx_auxo_HashArray $resolvers) {
		$this->resolvers = $resolvers;
	}
	
	/**
	 * Setter for the component factory
	 *
	 * @param tx_auxo_ComponentFactory $factory
	 */
	public function setComponentFactory(tx_auxo_ComponentFactory $factory) {
		$this->factory = $factory;	
	}	
	
	/**
	 * Setter for a filter chain 
	 *
	 * @param tx_auxo_FilterChain $filterChain a filter chain object
	 */
	public function setFilterChain(tx_auxo_FilterChain $filterChain) {
		$this->filterChain = $filterChain;
	}
		
	/**
	 * Determines a controller to handle this request and delegates all work to this
	 * class.
	 *
	 * @param tx_auxo_Request $request A web request
	 * @param tx_auxo_Response $response A web response
	 * @throws tx_auxo_NoControllerFoundException thrown if no controller has been resolved
	 */
	public function handleRequest(tx_auxo_Request $request, tx_auxo_Response $response) {
		$controllerClass = $this->getController($request);
		$controller = $this->factory->get($controllerClass);
		$this->filterChain->setFilter(new tx_auxo_FilterControllerAdapter($controller));
		return $this->filterChain->invoke($request, $response);
	}
	
	/**
	 * Returns the priority of this request handler
	 *
	 * @return int $priority priority of this request handler
	 */
	public function getPriority() {
		return self::HANDLER_PRIORITY;
	}
	
	/**
	 * Determines a controller that handles the current request
	 *
	 * @param tx_auxo_Request $request a request
	 * @return string $className controller class name
	 * @throws tx_auxo_InvalidArgumentException thrown if a resolver did not implement tx_auxo_ControllerResolverInterface
	 * @throws tx_auxo_NoControllerFoundException thrown if no controller could be determined by any resolver
	 */
	protected function getController(tx_auxo_Request $request) {
		foreach($this->resolvers as $resolver) {
			if (! $resolver instanceof tx_auxo_ControllerResolverInterface) {
				throw new tx_auxo_InvalidArgumentException(sprintf('Controller resolver %s with unexcepted type', getClass($resolver)));
			}
			
			if (($controllerClass = $this->controllerResolver->resolve($request))) {
				return $controllerClass;
			}			
		}
		throw new tx_auxo_NoControllerFoundException(sprintf('Controller could not be resolved'));		
	}
}
?>